package com.java.Lock.ReentrantLock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * ReentrantLock解决线程安全问题
 */
public class ReentrantLockTicket {
    static class ThreadSon extends Thread {
        // static修饰是因为票的数量应该被所有窗口共享
        static int ticket = 0;

        // Lock实现类实例对象相当于钥匙(锁对象)
        static Lock lock = new ReentrantLock(); // static修饰是因为该对象应该被所有窗口共享，即钥匙是同一把

        @Override
        public void run() {
            while (true) { // while不能在同步代码块内部，否则票将由同一窗口卖
                try {
                    lock.lock(); // 拿走钥匙关锁⭐⭐⭐
                    if (ticket > 9) {
                        break;
                    }

                    Thread.sleep(10); // 模拟窗口出票延时

                    ticket++;
                    System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock(); // 归还钥匙开锁⭐⭐⭐
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new ThreadSon().start();
        new ThreadSon().start();
        new ThreadSon().start();
    }

    /**
     * 输出结果如下，每次运行的结果不同！未出现重复卖或卖超的问题
     * Thread-0正在卖第1张票
     * Thread-2正在卖第2张票
     * Thread-1正在卖第3张票
     * Thread-1正在卖第4张票
     * Thread-0正在卖第5张票
     * Thread-2正在卖第6张票
     * Thread-2正在卖第7张票
     * Thread-0正在卖第8张票
     * Thread-1正在卖第9张票
     * Thread-0正在卖第10张票
     */
}
